
# include "dfxThread_Win32.h"
# include "dfxLog.h"

namespace DFX
{
    UInt32 WINAPI ThreadEntryPoint(void *ptr)
    {
        Task *t = reinterpret_cast<Task*>(ptr);

        if (t)        
            t->Run();        

        _endthreadex(0);

        return NULL;
    }

    Thread_Win32::Thread_Win32(PRIORITY pri)
        : Thread(pri), mHandle(0)
    {
    }

    Thread_Win32::~Thread_Win32()
    {
    }

    void Thread_Win32::Start(Task *t)
    {        
        UInt32 threadId = 0;        
        Int32 priority = THREAD_PRIORITY_IDLE;

        mHandle = _beginthreadex(NULL, 0, ThreadEntryPoint, (void*)t, 0, &threadId);

        if (t)
            t->SetThread(this);
        
        switch (mPriority)
        {
        case PRIORITY_LOWEST:
            priority = THREAD_PRIORITY_LOWEST;
            break;

        case PRIORITY_LOW:
            priority = THREAD_PRIORITY_BELOW_NORMAL;
            break;

        case PRIORITY_NORMAL:
            priority = THREAD_PRIORITY_NORMAL;
            break;

        case PRIORITY_HIGH:
            priority = THREAD_PRIORITY_ABOVE_NORMAL;
            break;

        case PRIORITY_HIGHEST:
            priority = THREAD_PRIORITY_HIGHEST;
            break;

        case PRIORITY_TIME_CRITICAL:
            priority = THREAD_PRIORITY_TIME_CRITICAL;
            break;
        }

        SetThreadPriority((HANDLE)mHandle, priority);
    }

    void Thread_Win32::Exit(bool wait)
    {
        mPendingExit = true;

        if (!wait)
            return;

        if (GetCurrentThreadId() != mHandle)
        {
            WaitForSingleObject((HANDLE)mHandle, INFINITE);
            CloseHandle((HANDLE)mHandle);
        }
    }
}